<?php

App::uses('AppController', 'Controller');

/**
 * Categories Controller
 *
 * @property Category $Category
 * @property SessionComponent $Session
 */
class CategoriesController extends AppController {

    const ORDER_ASC = 'ASC';
    const ORDER_DESC = 'DESC';
    const SEPARATOR = '____';

    /**
     * Components
     *
     * @var array
     */
    public $components = array('Session');

    /**
     * index method
     *
     * @return void
     */
    public function index() {
        $data = $this->Category->generateTreeList(null, null, null, CategoriesController::SEPARATOR);
        $this->set('categories', $data);
    }

    /**
     * view method
     *
     * @throws NotFoundException
     * @param string $id
     * @return void
     */
    public function view($id = null) {
        if (!$this->Category->exists($id)) {
            throw new NotFoundException(__('Invalid category'));
        }
        $options = array('conditions' => array('Category.' . $this->Category->primaryKey => $id));
        $this->set('category', $this->Category->find('first', $options));
    }

    /**
     * add method
     *
     * @param int $parent default value for form
     * @return void
     */
    public function add($parent = null) {
        if ($this->request->is('post')) {
            $this->Category->create();
            if ($this->Category->save($this->request->data)) {
                $this->Session->setFlash(__('The category has been saved.'));
                return $this->redirect(array('action' => 'index'));
            } else {
                $this->Session->setFlash(__('The category could not be saved. Please, try again.'));
            }
        }
        $this->_setParentsList($parent);
    }

    /**
     * edit method
     *
     * @throws NotFoundException
     * @param string $id
     * @return void
     */
    public function edit($id = null) {
        if (!$this->Category->exists($id)) {
            throw new NotFoundException(__('Invalid category'));
        }
        if ($this->request->is(array('post', 'put'))) {
            if ($this->Category->save($this->request->data)) {
                $this->Session->setFlash(__('The category has been saved.'));
                return $this->redirect(array('action' => 'index'));
            } else {
                $this->Session->setFlash(__('The category could not be saved. Please, try again.'));
            }
        }
        $options = array('conditions' => array('Category.' . $this->Category->primaryKey => $id));
        $this->request->data = $this->Category->find('first', $options);
        $this->_setParentsList();
    }

    /**
     * delete method
     *
     * @throws NotFoundException
     * @param string $id
     * @return void
     */
    public function delete($id = null) {
        $this->Category->id = $id;
        if (!$this->Category->exists()) {
            throw new NotFoundException(__('Invalid category'));
        }
        $this->request->allowMethod('post', 'delete');
        if ($this->Category->removeFromTree($id, true)) {
            $this->Session->setFlash(__('The category has been deleted.'));
        } else {
            $this->Session->setFlash(__('The category could not be deleted. Please, try again.'));
        }
        return $this->redirect(array('action' => 'index'));
    }

    private function _setParentsList($parent = null) {
        $parents = $this->Category->generateTreeList(null, null, null, CategoriesController::SEPARATOR);
        $this->set(compact('parents'));
        if (!empty($parent)) {
            if ($this->Category->exists($parent)) {
                $options = array($this->Category->name => array(
                        'parent_id' => $parent
                ));
                $this->request->data = $options;
            }
        }
    }

    /**
     * sort by name
     * 
     * @param int $order CategoriesController::ORDER_ASC - 'ASC'\n CategoriesController::ORDER_DESC - 'DESC'
     * @return redirect
     */
    public function sortByName($order = CategoriesController::ORDER_ASC) {
        $this->Category->recover();
        if ($order == CategoriesController::ORDER_ASC) {
            $this->Category->reorder(array('field' => 'name', 'order' => 'ASC'));
        } elseif ($order == CategoriesController::ORDER_DESC) {
            $this->Category->reorder(array('field' => 'name', 'order' => 'DESC'));
        }
        return $this->redirect(array('action' => 'index'));
    }

    /**
     * Similar to generateTreeList(), but returns part of tree. Recursive method.
     * 
     * @param int $id Root of subTree.
     * @param array $tree Initial array.
     * @param int $depth Initial depth. Practically, this means the number of separators.
     * @return array If $id is null returns generateTreeList(null, null, null, CategoriesController::SEPARATOR).
     */
    private function _generateSubTreeList($id = null, $tree = array(), $depth = 0) {
        if (empty($id)) {
            return $this->Category->generateTreeList(null, null, null, CategoriesController::SEPARATOR);
        } else {
            $directChildren = $this->Category->children($id, true);
            foreach ($directChildren as $directChild) {
                $idChild = $directChild['Category']['id'];
                $tree[$idChild] = str_repeat(CategoriesController::SEPARATOR, $depth) . $directChild['Category']['name'];
                if ($this->Category->childCount($idChild) > 0) {
                    $tree = $this->_generateSubTreeList($idChild, $tree, $depth + 1);
                }
            }
            return $tree;
        }
    }

}
